<template>
	<leo-list ref="leoListRef" @scroll="scroll" @getListApi="getListApi" :loadingMoreEnabled="loadingMoreEnabled" :refresherEnabled="refresherEnabled" :scrollable="scrollable" @getViewInfo="getViewInfo">
		<!-- 四位插槽 -->
		<template #top>
			<slot name="top"></slot>
		</template>
		<template #left>
			<slot name="left"></slot>
		</template>
		
		
		<!-- #ifdef MP-WEIXIN -->
		<template #list={dataList}>
			<leo-drag :supportLongpress="supportLongpress" @pressStart="pressStart" @getAreaStyle="getAreaStyle" @handleMoving="handleMoving" :dragDirection="dragDirection" :swapMode="true" @handleDragStart="handleDragStart" :column="1" ref="leoDragRef" id="leoDragRef" @getList="getList" :list="dataList">
				<template #content={data}>
					{{data.key}}
					<slot :data="data" name="content"></slot>
				</template>
			</leo-drag>
		</template>
		<!-- #endif -->
		
		
		
		
		<!-- #ifndef MP-WEIXIN -->
		<template #list={dataList}>
			<leo-drag :supportLongpress="supportLongpress" @pressStart="pressStart" @getAreaStyle="getAreaStyle" @handleMoving="handleMoving" :dragDirection="dragDirection" :swapMode="true" @handleDragStart="handleDragStart" :column="1" ref="leoDragRef" id="leoDragRef" @getList="getList" :list="dataList">
				<template #content={data}>
					<slot :data="data" name="content"></slot>
				</template>
			</leo-drag>
		</template>
		<!-- #endif -->
		<template #right>
			<slot name="right"></slot>
		</template>
		<template #bottom>
			<slot name="bottom"></slot>
		</template>
	</leo-list>
</template>

<script>
	export default{
		props:{
			supportLongpress:{		// 是否支持长按
				type: Boolean,
				default: true
			}
		},
		emits:['touchTheTop','touchTheBottom','getListApi'],
		data:{
			return {
				dataset:{},
				refresherEnabled:true,
				dragDirection = 'down',	// 拖拽方向： upward-向上， down-向下
				lazyDragDirection = '',			// 拖拽方向： 延迟处理方向状态 - 专门用于判断触边状态的调整
				dragY = 0,						// 记录拖拽时y轴的位置
				dragX = 0,						// 记录拖拽时x轴的位置
				dragElHeight = 0,				// 拖拽元素的高度
				
				scrollable = true,			// 是否支持滚动
				loadingMoreEnabled = true,	// 是否支持触底加载
				scrollTop = 0,					// 滚动产生的顶部边距,需要扣除的顶部距离
				maxHeight = 0,					// 拖拽的高度
				scrollToYTimer = null,			// 滚动定时器
				scrollToStatus = false,			// 触边滚动状态
				scrollvalue = 0,				// 实际上滚动的值
				throttleTimerScroll = ,//节流函数
			}
		},
		onLoad() {
			this.throttleTimerScroll = this.throttle(this.timerScroll,1000);
		},
		methods:{
			// 获取列表
			getListApi({dataList,callback}){
				// 模拟api请求 --- 需要传递请求回来的列表和总条数
				setTimeout(()=>{
					let lists = [];
					for (var i = dataList.length; i < dataList.length+10; i++) {
						lists.push({name:i})
					}
					callback(lists, 300);	// 和complete用法一致, 第二参数需要传递数据库的总数量
				},200)
			},
			// 按下事件
			pressStart(e){
				this.dragY = e.data.y;				// 触摸位置
				this.dragX = e.data.x;				// 触摸位置
				this.dragElHeight = e.data.height;	// 元素高度
			},
			// 拖动中
			handleMoving(e){
				// 判断和赋值
				this.dragDirection = e.y > this.dragY?'down':'upward'; // 方向
				this.dragY = e.y;		// 记录y轴位置
				this.dragX = e.x;		// 记录x轴位置
				
				// 是否到了指定位置
				// 预计为总高度的5/1
				let touchValue = this.dataset.height/5;	// 触碰边缘的值
				let touchPoint = this.dragY-this.scrollTop;	// 触碰点
				if(!this.scrollToStatus){
					// 当非拖拽状态时，重新赋值向上还是向下 
					this.lazyDragDirection = this.dragDirection;
				}
				if(this.lazyDragDirection === 'down'){
					// 如果是向下，则还需要添加自身高度
					touchPoint+=this.dragElHeight;
					if(touchPoint >= this.dataset.height-touchValue){
						this.throttleTimerScroll(touchValue);
					} else{
						this.nonTouchingState();
					}
				} else if(this.lazyDragDirection === 'upward'){
					if(touchPoint <= touchValue){
						this.throttleTimerScroll(-touchValue);
					} else{
						this.nonTouchingState();
					}
				} else{
					this.nonTouchingState();
				}
			},
			// 非触边状态--重置触边
			nonTouchingState(){
				clearTimeout(this.scrollToYTimer)
				this.scrollToStatus = false;
				this.lazyDragDirection = '';
			},
			// 拖拽结束
			getList(e){
				this.refresherEnabled = true;
				this.scrollable = true;
				this.scrollToStatus = false;
				this.loadingMoreEnabled = true;
				clearTimeout(this.scrollToYTimer)
			},
			// 滚动中-需要记录滚动的距离
			scroll(e){
				this.scrollTop = e.detail.scrollTop;
			},
			// 定时触发滚动
			timerScroll(e){
				if(this.scrollToStatus) return;
				this.scrollToStatus = true;
				if(!this.scrollToStatus || this.refresherEnabled) return; // 非拖拽状态
				this.scrollToY(e);		// 触发滚动
				this.setTimerScroll(e);	// 回调
			},
			// 定时触发滚动
			setTimerScroll(e){
				this.scrollToYTimer = setTimeout(()=>{
					if(!this.scrollToStatus || this.refresherEnabled) return; // 非拖拽状态
					this.scrollToY(e);		// 触发滚动
					this.setTimerScroll(e);	// 回调
				},700)
			},
			// 获取内容区域
			getViewInfo(e){
				this.dataset = e;
			},
			// 获取视图高度
			getAreaStyle(e){
				this.maxHeight = parseFloat(e.height);
			},
			// 允许拖拽状态--let-drag的emit触发
			handleDragStart(i){
				this.refresherEnabled = false;
				this.scrollable = false;
				this.loadingMoreEnabled = false;
			},
			// 让父等触发拖拽
			handleLongpress(i){
				this.$ref.leoDragRef.handleLongpress(i);
			},
			// 滚动触发
			scrollToY(e){
				this.scrollable = true;
				let roll = e;
				if(this.lazyDragDirection === 'upward'){
					if(this.scrollTop <= 0){
						return; // 滚动条到顶了
					};
					if(roll < -this.scrollTop){
						// 需要滚动距离 < 顶部可滚动距离  - 则把剩余滚动值赋予roll
						// emit('touchTheTop')
						roll = -this.scrollTop;	// scrollTop 目前滚动条位置 然后用负数 代替 实现到顶位置
					};
				} else if(this.lazyDragDirection === 'down'){
					// 窗口高度+目前滚动距离+需滚动距离 > 顶部可滚动距离  - 则把最大值赋给roll
					let maxScroll = this.dataset.height + this.scrollTop;
					let scrollDown = this.dataset.height + this.scrollTop + e; // 向下滚动 产生的最大值
					// 1. 剩余可滚动 + 窗口高度
					if(this.maxHeight - this.maxScroll < 2) {
						 // 如果产生的总滚动px小于2px ，那么不触发滚动
						return
					};
					if(this.scrollDown > this.maxHeight){
						// 可滚动距离是多少？
						// this.$emit('touchTheBottom')
						roll = maxHeight - maxScroll;
					}
				}
				this.$nextTick(()=>{
					setTimeout(()=>{
						this.$ref.leoDragRef.changeScrollInfo({y:roll});// 滚动产生的距离
					},300)
					this.$ref.leoListRef.scrollIntoViewByNodeTop(roll);	// 滚动
				})
			},
			// 节流函数
			throttle(fn, interval, options = {leading: true,trailing: false}) {
			  // 1.记录上一次的开始时间
			  const { leading,trailing} = options
			  let lastTime = 0
			  let timer = null
			 
			  // 2.事件触发时, 真正执行的函数
			  const _throttle = function (...args) {
			    return new Promise((resolve, reject) => { //promise方式返回返回值
			      // 2.1.获取当前事件触发时的时间
			      const nowTime = new Date().getTime()
			      if (!lastTime && !leading) lastTime = nowTime
			 
			      // 2.2.使用当前触发的时间和之前的时间间隔以及上一次开始的时间, 计算出还剩余多长事件需要去触发函数
			      const remainTime = interval - (nowTime - lastTime)
			      if (remainTime <= 0) {
			        if (timer) {
			          clearTimeout(timer)
			          timer = null
			        }
			 
			        // 2.3.真正触发函数
			        const result = fn.apply(this, args)
			        resolve(result)
			        // 2.4.保留上次触发的时间
			        lastTime = nowTime
			        return
			      }
			 
			      if (trailing && !timer) {
			        timer = setTimeout(() => {
			          const result = fn.apply(this, args)
			          resolve(result)
			          timer = null
			          lastTime = !leading ? 0 : new Date().getTime()
			        }, remainTime)
			      }
			    })
			  }
			 
			  _throttle.cancel = function () {
			    if (timer) clearTimeout(timer)
			    timer = null
			    lastTime = 0
			  }
			 
			  return _throttle
			}
		}
	}
</script>

<style scoped lang="scss">

</style>